//
//  Render.m
//  whfdemo004
//
//  Created by 王洪飞 on 2024/6/14.
//

#import "Render.h"
#import "GLProgram.h"
#import <GLKit/GLKit.h>
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"


@interface Render ()
{
    CGFloat dwidth;
    CGFloat dheight;
    GLuint vaoId;
    GLKMatrix4 modelViewMatrix;
    GLKMatrix4 projectMatrix;
    GLuint mCount;
    GLuint mDefaultFBO;
    GLuint mExtraFBO;
    GLuint mExtraDepthBuffer;
    GLuint mExtraTexture;
    
}
@property (nonatomic, strong) GLProgram *program;
@property (nonatomic, strong) GLProgram *baseProgram;

@property (nonatomic , assign) long mBaseRotate;
@property (nonatomic , assign) long mExtraRotate;
@end

@implementation Render
- (instancetype)initWidth:(CGFloat)width height:(CGFloat)height
{
    self = [super init];
    if (self) {
        dwidth = width;
        dheight = height;
        [self loadTexture];
        [self initMVP];
        [self prepareData];
        [self setupProgram];

    }
    return self;
}



-(void)initMVP {
    projectMatrix = GLKMatrix4MakePerspective(
                                              GLKMathDegreesToRadians(85.0f),
                                              dwidth / dheight,
                                              0.1f,
                                              20.0f);
    modelViewMatrix = GLKMatrix4MakeLookAt(
                                           0.0, 0.0, 3.0,   // Eye position
                                           0.0, 0.0, 0.0,   // Look-at position
                                           0.0, 1.0, 0.0);  // Up direction
}

-(void)loadTexture{
    NSString* filePath = [[NSBundle mainBundle] pathForResource:@"for_test" ofType:@"png"];
    NSString* filePath1 = [[NSBundle mainBundle] pathForResource:@"container" ofType:@"jpg"];
    NSDictionary* options = [NSDictionary dictionaryWithObjectsAndKeys:@(1), GLKTextureLoaderOriginBottomLeft, nil];

    GLKTextureInfo* textureInfo = [GLKTextureLoader textureWithContentsOfFile:filePath options:options error:nil];
    GLKTextureInfo* textureInfo1 = [GLKTextureLoader textureWithContentsOfFile:filePath1 options:options error:nil];
    
//    glBindTexture(GL_TEXTURE_2D, textureInfo.name);
    NSLog(@"load texture %d : %x: %x : %x", textureInfo.name, textureInfo.target, GL_TEXTURE0, GL_TEXTURE_2D);
    NSLog(@"load texture1 %d : %x: %x : %x", textureInfo1.name, textureInfo1.target, GL_TEXTURE0, GL_TEXTURE_2D);
}

-(void)setupProgram{
    NSString *vShaderStr = @""
    "#version 300 es \n"
    "layout(location = 0) in vec3 vPos;\n"
    "layout(location = 1) in vec3 vColor;\n"
    "layout(location = 2) in vec2 vCoord;\n"
    "uniform mat4 projection;\n"
    "uniform mat4 mv;\n"
    "out vec3 vsColor;\n"
    "out vec2 vsCoord; \n"
    "void main(){gl_Position = projection * mv * vec4(vPos, 1.0);\n"
    "vsColor = vColor;\n"
    "vsCoord = vCoord;\n"
    "}";
    NSString *fShaderStr = @""
    "#version 300 es \n"
    "precision mediump float; \n"
    "uniform sampler2D s_texture;\n"
    "uniform sampler2D s_texture1;\n"
    "in vec3 vsColor;\n"
    "in vec2 vsCoord; \n"
    "out vec4 fragColor;\n"
    "void main(){fragColor = mix(texture(s_texture1, vsCoord) , vec4(vsColor,1), 0.2) ;}";
//    "void main(){fragColor = texture(s_texture1, vsCoord) * vec4(vsColor,1);}";
    self.program = [[GLProgram alloc] initWithVertexShaderString:vShaderStr fragmentShaderString:fShaderStr];

    if ([self.program link]) {
        NSLog(@"link successs");
        
        
    }
    
    NSString *vShaderStr1 = @""
    "#version 300 es \n"
    "layout(location = 0) in vec3 vPos;\n"
    "void main(){gl_Position = vec4(vPos, 1.0);}";
    NSString *fShaderStr1 = @""
    "#version 300 es \n"
    "precision mediump float; \n"
    "out vec4 fragColor;\n"
    "void main(){fragColor = vec4(0.0,0.5,0.6,1);}";
    
    self.baseProgram = [[GLProgram alloc] initWithVertexShaderString:vShaderStr1 fragmentShaderString:fShaderStr1];
    if([self.baseProgram link]){
        NSLog(@"base program link success");
        
      
    }
}

-(void)prepareData {
    GLfloat vertices[] = {
        -1.0f, 1.0f, 0.0f,      0.0f, 0.0f, 1.0f,       0.0f, 1.0f,//左上
        1.0f, 1.0f, 0.0f,       0.0f, 1.0f, 0.0f,       1.0f, 1.0f,//右上
        -1.0f, -1.0f, 0.0f,     1.0f, 0.0f, 1.0f,       0.0f, 0.0f,//左下
        1.0f, -1.0f, 0.0f,      0.0f, 0.0f, 1.0f,       1.0f, 0.0f,//右下
        0.0f, 0.0f, 1.0f,       1.0f, 1.0f, 1.0f,       0.5f, 0.5f,//顶点
    };
    GLubyte indices[] = {
//        0,1,2,0,2,3
        0, 3, 2,
        0, 1, 3,
    };
    glGenVertexArrays(1, &vaoId);
    glBindVertexArray(vaoId);
    
    GLuint vboId, eboId;
    glGenBuffers(1, &vboId);
    glBindBuffer(GL_ARRAY_BUFFER, vboId);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
    
    glGenBuffers(1, &eboId);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, eboId);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
    
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 8, (void *)0);
    glEnableVertexAttribArray(0);
 
    glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 8, (GLfloat *)NULL + 3);
    glEnableVertexAttribArray(1);
 
    glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 8, (GLfloat *)NULL + 6);
    glEnableVertexAttribArray(2);
 
    glBindVertexArray(0);
    glBindBuffer(GL_ARRAY_BUFFER, 0);
 
}

- (void)update:(BOOL)baseOn
{
//    GLKMatrix4 modelViewMatrix;
    if (baseOn) {
        NSLog(@"rotate %ld", self.mBaseRotate);
        ++self.mBaseRotate;
        modelViewMatrix = GLKMatrix4MakeLookAt(
                                               0.0, 0.0, 3.0,   // Eye position
                                               0.0, 0.0, 0.0,   // Look-at position
                                               0.0, 1.0, 0.0);  // Up direction;
//        modelViewMatrix = GLKMatrix4Translate(modelViewMatrix, 0, 0, -3);
        modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, GLKMathDegreesToRadians(self.mBaseRotate), 0, 0, 1);
    }
    
//    if (self.mExtraSwitch.on) {
//        self.mExtraRotate += 2;
//        modelViewMatrix = GLKMatrix4Identity;
//        modelViewMatrix = GLKMatrix4Translate(modelViewMatrix, 0, 0, -3);
//        modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, GLKMathDegreesToRadians(self.mExtraRotate), 1, 1, 1);
//        self.mExtraEffect.transform.modelviewMatrix = modelViewMatrix;
//    }
}

-(void)draw{
//    modelViewMatrix = GLKMatrix4Identity;
//    modelViewMatrix = GLKMatrix4Translate(modelViewMatrix, 0, 0, -3);
//    modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, GLKMathDegreesToRadians(0), 1, 1, 1);
//    
    [self.program use];

  
    glUniformMatrix4fv([self.program uniformIndex:@"projection"], 1, false, (GLfloat *)&projectMatrix.m[0]);
    
    glUniformMatrix4fv([self.program uniformIndex:@"mv"], 1, false, (GLfloat *)&modelViewMatrix.m[0]);
    
    glBindVertexArray(vaoId);
    glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, NULL);
}
@end
